#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>

void srandom (unsigned seed);
double dboard (int darts);
#define DARTS 500000     /* number of throws at dartboard */
#define ROUNDS 10       /* number of times "darts" is iterated */
#define ROOT 0        /* task ID of master task */

int main (int argc, char *argv[])
{
	double	homepi,         /* value of pi calculated by current task */
		pisum,	        /* sum of tasks' pi values */
		pi,	        /* average of pi after "darts" is thrown */
		avepi;	        /* average pi value for all iterations */
	int	rank,	        /* task ID - also used as seed number */
		size,       /* number of tasks */
		rc,             /* return code */
		i;
	MPI_Status status;

	/* Obtain number of tasks and task ID */
	MPI_Init(&argc,&argv);
	MPI_Comm_size(MPI_COMM_WORLD,&size);
	MPI_Comm_rank(MPI_COMM_WORLD,&rank);
	printf ("MPI task %d has started...\n", rank);
	if (rank == ROOT) 
		printf ("Using %d tasks to compute pi (3.1415926535)\n",size);

	/* Set seed for random number generator equal to task ID */
	srandom (rank);

	avepi = 0;
	for (i = 0; i < ROUNDS; i++) {
		/* All tasks calculate pi using dartboard algorithm */
		homepi = dboard(DARTS/size);

		/* Use MPI_Reduce to sum values of homepi across all tasks 
		 * Master will store the accumulated value in pisum 
		 * - homepi is the send buffer
		 * - pisum is the receive buffer (used by the receiving task only)
		 * - the size of the message is sizeof(double)
		 * - ROOT is the task that will receive the result of the reduction
		 *   operation
		 * - MPI_SUM is a pre-defined reduction function (double-precision
		 *   floating-point vector addition).  Must be declared extern.
		 * - MPI_COMM_WORLD is the group of tasks that will participate.
		 */

		rc = MPI_Reduce(&homepi, &pisum, 1, MPI_DOUBLE, MPI_SUM,
										ROOT, MPI_COMM_WORLD);

		if (rc != MPI_SUCCESS)  printf("%d: failure on mpc_reduce\n", rank);

		/* Master computes average for this iteration and all iterations */
		if (rank == ROOT) {
      pi = pisum/size;
      avepi = ((avepi * i) + pi)/(i + 1); 
		}    
	} 

	if(rank==ROOT)
	printf("   After %8d throws, average value of pi = %10.8f\n",
				 (DARTS * (ROUNDS + 1)),avepi);

	MPI_Finalize();
	return 0;
}
